package com.crazy.proxy;

import cn.hutool.aop.aspects.Aspect;
import cn.hutool.core.util.ReflectUtil;
import org.apache.poi.ss.formula.functions.T;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author panyonghui
 * @describe 基于jdk动态代理（被代理对象必须要实现接口）
 * @date 2023/1/5 16:50
 */
public class JdkProxy {
    /**
     * @describe
     * @param target 被代理类的对象
     * @param aspectClass 需要执行的切面类
     * @return T
     * @modify
     */
    public static <T> T getProxyInstance(T target, Class aspectClass) {
        // 需要执行的切面对象
//        Aspect aspect = (Aspect) ReflectUtil.newInstance(aspectClass, new Object[0]);
        Aspect aspect = null;
        try {
            aspect = (Aspect) aspectClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Aspect finalAspect = aspect;
        InvocationHandler invocationHandler = (proxy, method, args) -> {
            // 原方法执行前的额外任务
            finalAspect.before(target, method, args);
            // obj：被代理类的对象
            Object result = method.invoke(target, args);
            // 执行完原方法后可执行额外的任务
            finalAspect.after(target, method, args, result);
            return result;
        };
        // 第二个参数的意思：因为被代理类和代理类要实现同样的接口
        return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocationHandler);
    }
}
